import AVFoundation
import UIKit


protocol CameraDelgate: NSObjectProtocol {
    
    func capturePhoto(data: Data?, error: (any Error)?)
    
}

final class CameraManager: NSObject {
    
    typealias PhotoCaptureCompletion = (Data?, Error?) -> Void
    typealias VideoCaptureCompletion = (URL?, Error?) -> Void
    
    static let shared = CameraManager()
    
    // MARK: - Properties
    private var captureSession: AVCaptureSession?
    private var currentCamera: AVCaptureDevice?
    private var frontCamera: AVCaptureDevice?
    private var backCamera: AVCaptureDevice?
    private var photoOutput: AVCapturePhotoOutput?
    private var videoOutput: AVCaptureMovieFileOutput?
    private var previewLayer: AVCaptureVideoPreviewLayer?
    
    // Camera configuration
    private(set) var flashMode: AVCaptureDevice.FlashMode = .off
    private(set) var cameraPosition: AVCaptureDevice.Position = .back
    private(set) var focusMode: AVCaptureDevice.FocusMode = .continuousAutoFocus
    private(set) var exposureMode: AVCaptureDevice.ExposureMode = .continuousAutoExposure
    private(set) var isRecording = false
    
    public weak var delegate: CameraDelgate?
    
    private override init() {
        super.init()
        setupCaptureSession()
    }
    
    
    
    
}

// MARK: - Private Methods
private extension CameraManager {
    func setupCaptureSession() {
        captureSession = AVCaptureSession()
        setupCameras()
        setupPreviewLayer()
        setupPhotoOutput()
        setupVideoOutput()
    }
    /**
     * - builtInWideAngleCamera: 表示内置广角摄像头
     * - unspecified:表示不指定位置，会返回所有位置的摄像头
     */
    func setupCameras() {
        let session = AVCaptureDevice.DiscoverySession(
            deviceTypes: [.builtInWideAngleCamera], // 要查找的设备类型数组
            mediaType: .video, // 媒体类型
            position: .unspecified // 摄像头位置
        )
        
        for device in session.devices {
            switch device.position {
            case .front:
                frontCamera = device
            case .back:
                backCamera = device
            default:
                break
            }
        }
        
        currentCamera = backCamera
        guard let camera = currentCamera else { return }
        
        do {
            let input = try AVCaptureDeviceInput(device: camera)
            if captureSession?.canAddInput(input) == true {
                captureSession?.addInput(input)
            }
        } catch {
            print("Error setting up camera: \(error.localizedDescription)")
        }
    }
    
    func setupPreviewLayer() {
        guard let captureSession = captureSession else { return }
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer?.videoGravity = .resizeAspectFill
    }
    
    func setupPhotoOutput() {
        photoOutput = AVCapturePhotoOutput()
        guard let photoOutput = photoOutput,
              captureSession?.canAddOutput(photoOutput) == true else { return }
        captureSession?.addOutput(photoOutput)
    }
    
    func setupVideoOutput() {
        videoOutput = AVCaptureMovieFileOutput()
        guard let videoOutput = videoOutput,
              captureSession?.canAddOutput(videoOutput) == true else { return }
        captureSession?.addOutput(videoOutput)
    }
}

// MARK: - Public Methods
extension CameraManager {
    
    /// 开始预览
    func startPreview(in view: UIView) {
        guard let previewLayer = previewLayer else { return }
        previewLayer.frame = view.bounds
        view.layer.addSublayer(previewLayer)
        captureSession?.startRunning()
    }
    
    /// 停止预览
    func stopPreview() {
        captureSession?.stopRunning()
    }
    
    /// 切换摄像头
    func switchCamera() throws {
        guard let currentCamera = currentCamera,
              let captureSession = captureSession else { return }
        
        let newPosition: AVCaptureDevice.Position = currentCamera.position == .back ? .front : .back
        let newCamera = newPosition == .back ? backCamera : frontCamera
        
        guard let newCamera = newCamera else { return }
        
        captureSession.beginConfiguration()
        
        let currentInput = captureSession.inputs.first as? AVCaptureDeviceInput
        captureSession.removeInput(currentInput!)
        
        let newInput = try AVCaptureDeviceInput(device: newCamera)
        if captureSession.canAddInput(newInput) {
            captureSession.addInput(newInput)
            self.currentCamera = newCamera
            self.cameraPosition = newPosition
        }
        
        captureSession.commitConfiguration()
    }
    
    /// 设置闪光灯模式
    func setFlashMode(_ mode: AVCaptureDevice.FlashMode) {
        self.flashMode = mode
    }
    
    /// 设置手动聚焦点
    func focus(at point: CGPoint) throws {
        guard let device = currentCamera else { return }
        
        try device.lockForConfiguration()
        if device.isFocusPointOfInterestSupported {
            device.focusPointOfInterest = point
            device.focusMode = .autoFocus
        }
        device.unlockForConfiguration()
    }
    
    /// 设置曝光点
    func setExposure(at point: CGPoint) throws {
        guard let device = currentCamera else { return }
        
        try device.lockForConfiguration()
        if device.isExposurePointOfInterestSupported {
            device.exposurePointOfInterest = point
            device.exposureMode = .autoExpose
        }
        device.unlockForConfiguration()
    }
    
    /// 设置ISO值
    func setISO(_ iso: Float) throws {
        guard let device = currentCamera else { return }
        
        try device.lockForConfiguration()
        device.setExposureModeCustom(duration: device.exposureDuration, iso: iso)
        device.unlockForConfiguration()
    }
    
    /// 拍照
    func capturePhoto() {
        guard let photoOutput = photoOutput else {
            delegate?.capturePhoto(data: nil, error: NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Photo output not available"]))
            return
        }
        let settings = AVCapturePhotoSettings()
        settings.flashMode = self.flashMode
        photoOutput.capturePhoto(with: settings, delegate: self)
    }
    
    /// 开始录制视频
    func startRecording(to outputURL: URL) {
        guard let videoOutput = videoOutput else { return }
        if !videoOutput.isRecording {
            videoOutput.startRecording(to: outputURL, recordingDelegate: self)
            isRecording = true
        }
    }
    
    /// 停止录制视频
    func stopRecording() {
        guard let videoOutput = videoOutput else { return }
        if videoOutput.isRecording {
            videoOutput.stopRecording()
            isRecording = false
        }
    }
}

// MARK: - AVCaptureFileOutputRecordingDelegate
extension CameraManager: AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        if let error = error {
            print("Error recording video: \(error.localizedDescription)")
            return
        }
        
        // 处理录制的视频
    }
    
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        // 开始录制视频的回调
    }
}
